home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gnat1792.zip
/
gnat179b
/
t-adainc
/
a-ngelfu.adb
< prev
next >
Wrap
Text File
|
1994-05-19
|
20KB
|
763 lines
------------------------------------------------------------------------------
-- --
-- GNAT RUNTIME COMPONENTS --
-- --
-- A D A . N U M E R I C S . G E F --
-- --
-- B o d y --
-- --
-- $Revision: 1.2 $ --
-- --
-- Copyright (c) 1992,1993,1994 NYU, All Rights Reserved --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
-- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
-- This body is specifically for using an Ada interface to C math.h
-- to get the computation engine
-- Many special cases are handled locally to avoid unnecessary calls
-- All Ada required exception handling is provided.
-- This is not a "strict" implementation.
-- This is an early, trial, implementation; simplified for early gnat.
-- uses: sqrt, exp, log, pow, sin, asin, cos, acos, tan, atan,
-- sinh, cosh, tanh
with Ada.Numerics.Aux; -- interface to C library via math.h is in this package
package body Ada.Numerics.Generic_Elementary_Functions is
subtype Double is Ada.Numerics.Aux.Double;
Pi : constant := 3.14159_26535_89793_23846_26433_83279_50288_41972;
Log_Two : constant := 0.69314_71805_59945_30941_72321_21458_17656_80755;
Two_Pi : Float_Type'Base;
Half_Pi : Float_Type'Base;
Fourth_Pi : Float_Type'Base;
Epsilon : Float_Type'Base;
Square_Root_Epsilon : Float_Type'Base;
Half_Log_Epsilon : Float_Type'Base;
Log_Last : Float_Type'Base;
Log_Inverse_Epsilon : Float_Type'Base;
function Exact_Remainder
(X : Float_Type'Base;
Y : Float_Type'Base)
return Float_Type'Base
is
Denominator : Float_Type'Base := abs X;
Divisor : Float_Type'Base := abs Y;
Reducer : Float_Type'Base;
Sign : Float_Type'Base := 1.0;
begin
if Y = 0.0 then
raise Constraint_Error;
elsif X = 0.0 then
return 0.0;
elsif X = Y then
return 0.0;
elsif Denominator < Divisor then
return X;
end if;
while Denominator >= Divisor loop
-- put divisors mantissa with denominators exponent to make reducer
Reducer := Divisor;
begin
while Reducer * 1_048_576.0 < Denominator loop
Reducer := Reducer * 1_048_576.0;
end loop;
exception
when others => null;
end;
begin
while Reducer * 1_024.0 < Denominator loop
Reducer := Reducer * 1_024.0;
end loop;
exception
when others => null;
end;
begin
while Reducer * 2.0 < Denominator loop
Reducer := Reducer * 2.0;
end loop;
exception
when others => null;
end;
Denominator := Denominator - Reducer;
end loop;
if X < 0.0 then
return -Denominator;
else
return Denominator;
end if;
end Exact_Remainder;
----------------
-- Local_Atan --
----------------
function Local_Atan
(Y : Float_Type'Base;
X : Float_Type'Base := 1.0)
return Float_Type'Base
is
Z : Float_Type'Base;
Raw_Atan : Float_Type'Base;
begin
if abs Y > abs X then
Z := abs (X / Y);
else
Z := abs (Y / X);
end if;
if Z < Square_Root_Epsilon then
Raw_Atan := Z;
elsif Z = 1.0 then
Raw_Atan := Pi / 4.0;
elsif Z < Square_Root_Epsilon then
Raw_Atan := Z;
else
Raw_Atan := Float_Type'Base (Ada.Numerics.Aux.Atan (Double (Z)));
end if;
if abs Y > abs X then
Raw_Atan := Half_Pi - Raw_Atan;
end if;
if X > 0.0 then
if Y > 0.0 then
return Raw_Atan;
else -- Y < 0.0
return -Raw_Atan;
end if;
else -- X < 0.0
if Y > 0.0 then
return Pi - Raw_Atan;
else -- Y < 0.0
return -(Pi - Raw_Atan);
end if;
end if;
end Local_Atan;
----------
-- Sqrt --
----------
function Sqrt (X : Float_Type'Base) return Float_Type'Base is
begin
if X < 0.0 then
raise Argument_Error;
elsif X = 0.0 then
return X; -- may be +0.0 or -0.0
elsif X = 1.0 then
return 1.0; -- needs to be exact for good COMPLEX accuracy
end if;
return Float_Type'Base (Ada.Numerics.Aux.Sqrt (Double (X)));
end Sqrt;
-------------------------
-- Log (natural base) --
-------------------------
function Log (X : Float_Type'Base) return Float_Type'Base is
begin
if X < 0.0 then
raise Argument_Error;
elsif X = 0.0 then
raise Constraint_Error;
elsif X = 1.0 then
return 0.0;
end if;
return Float_Type'Base (Ada.Numerics.Aux.Log (Double (X)));
end Log;
--------------------------
-- Log (arbitrary base) --
--------------------------
function Log (X, Base : Float_Type'Base) return Float_Type'Base is
begin
if X < 0.0 then
raise Argument_Error;
elsif Base <= 0.0 or else Base = 1.0 then
raise Argument_Error;
elsif X = 0.0 then
raise Constraint_Error;
elsif X = 1.0 then
return 0.0;
end if;
return Float_Type'Base (Ada.Numerics.Aux.Log (Double (X))
/ Ada.Numerics.Aux.Log (Double (Base)));
end Log;
---------
-- Exp --
---------
function Exp (X : Float_Type'Base) return Float_Type'Base is
Result : Float_Type'Base;
begin
if X = 0.0 then
return 1.0;
elsif X > Log_Last then
raise Constraint_Error;
end if;
return Float_Type'Base (Ada.Numerics.Aux.Exp (Double (X)));
exception
when others =>
raise Constraint_Error;
end Exp;
----------
-- "**" --
----------
function "**" (Left, Right : Float_Type'Base) return Float_Type'Base is
Result : Float_Type'Base;
begin
if Left = 0.0
and then Right = 0.0
then
raise Argument_Error;
elsif Left < 0.0 then
raise Argument_Error;
elsif Right = 0.0 then
return 1.0;
elsif Left = 0.0 then
if Right < 0.0 then
raise Constraint_Error;
else
return 0.0;
end if;
elsif Left = 1.0 then
return 1.0;
elsif Right = 1.0 then
return Left;
elsif Right = 2.0 then
return Left * Left;
end if;
return Float_Type'Base
(Ada.Numerics.Aux.pow (Double (Left), Double (Right)));
exception
when others =>
raise Constraint_Error;
end "**";
-------------------------
-- Sin (natural cycle) --
--------------